import matplotlib
import numpy as np
import math
import time

import pandas as pd
import xlrd
import matplotlib.pyplot as plt
import matplotlib.ticker as mtick
from matplotlib.pyplot import MultipleLocator
import copy
from PIL import Image

from .seismic import Seismic
from .gain import gain
from utils.index import saveRecord, resource_path


matplotlib.use('Agg')  # 使用非交互模式

def vspplot(cfg, progress_wrapper):
    #####################################################################
    # READ SEGY
    #####################################################################
    start = time.time()
    progress_wrapper.setValue(0)
    s1 = Seismic.from_segy(cfg['lp'])  # 拉平文件，读取
    s2 = Seismic.from_segy(cfg['stk'])  # 走廊文件，读取
    s3 = Seismic.from_segy(cfg['stkbf'])  # 滤波走廊文件，读取
    s4 = Seismic.from_segy(cfg['sei'])  # 地面文件，读取
    print(time.time() - start, '读取文件')

    print('************************')
    print("Read OK!")
    print("Start Agc!")

    # 设置极性
    if cfg['lpjx'] == 0:
        s1.data = -s1.data
    if cfg['stkjx'] == 0:
        s2.data = -s2.data
    if cfg['stkbfjx'] == 0:
        s3.data = -s3.data
    if cfg['seijx'] == 0:
        s4.data = -s4.data
    progress_wrapper.setValue(5)
    print(time.time() - start, '设置极性')

    # 抽稀和AGC
    if s1.dt < 1:
        sca = int(1 / s1.dt)
        s1.dt = 1.0
        s1.data = s1.data[::, ::sca]
    if cfg['lpagc'] == 0:
        s1.data = gain(s1.data, s1.dt, 'agc', cfg['agc'], 2)
        print('************************')
        print("拉平 AGC OK!")

    if cfg['stkagc'] == 0:
        s2.data = gain(s2.data, s2.dt, 'agc', cfg['agc'], 2)
        print('************************')
        print("走廊 AGC OK!")

    if cfg['stkbfagc'] == 0:
        s3.data = gain(s3.data, s3.dt, 'agc', cfg['agc'], 2)
        print('************************')
        print("滤波走廊 AGC OK!")

    if cfg['seiagc'] == 0:
        s4.data = gain(s4.data, s4.dt, 'agc', cfg['agc'], 2)
        print('************************')
        print("地面地震 AGC OK!")

    progress_wrapper.setValue(38)
    print(time.time() - start, '抽稀')
    print('************************')
    print("Start Plot!")

    # 读取分层文件中的内容
    if cfg['fcx'] == 1:
        df = pd.read_excel(cfg['fc'], sheet_name=0)  # sheet_name指定工作表编号或名称
        df.fillna('', inplace=True)  # 如果为空，则替换为空字符串
        zu = df.iloc[:, 0]  # 分组
        ywdh = df.iloc[:, 1]  # 英文代号
        dep = df.iloc[:, 2]  # 底深
        font = df.iloc[:, 3]  # 文字大小
        fzt = df.iloc[:, 4]  # 文字时间
        py = df.iloc[:, 5]  # 文字深度偏移
        ywdhpy = df.iloc[:, 6]  # 代号深度
        font1 = df.iloc[:, 7]  # 代号大小
    else:
        dep = []
        zu = []
        font = []
        font1 = []
        fzt = []
        py = []
        ywdh = []
        ywdhpy = []

    # dep = []
    # zu = []
    # font = []
    # font1 = []
    # fzt = []
    # py = []
    # ywdh = []
    # ywdhpy = []

    #####################################################################
    # MAKE PLOT
    #####################################################################

    # Plot size parameters.

    # Margins, CSS like: top, right, bottom, left.
    mt, mr, mb, ml = 0.3, 0.5, 0.3, 0.5

    # Determine plot dimensions. Kind of laborious and repetitive (see below).
    tpi = cfg['tpi']  # 拉平宽度
    ips = cfg['ips']  # 高度

    im = plt.imread(cfg['zhuzi'])  # 岩性柱子，读取图像文件
    im = im.swapaxes(1, 0)  # 用于交换数组的两个轴，将高度和宽度进行交换

    # 需要根据加密情况计算宽度
    seismic_width = 0
    brfi1 = 0  # cdp的差小于等于15的道数
    brfi2 = 0  # cdp的差大于15的道数
    brfl = len(s1.cdp)  # 数据一共有多少道
    for ii in range(0, brfl - 1):
        # 如果cdp大于最大绘制深度或小于最小绘制深度，则跳过该次循环
        if s1.cdp[ii] > cfg['lped'] or s1.cdp[ii] < cfg['lpsd']:
            continue
        if cfg['direction'] == 0:  # 数据深度从浅到深
            if s1.cdp[ii] - s1.cdp[ii + 1] > -15:  # 下一个cdp与当前cdp的差小于等于15
                brfi1 = brfi1 + 1
            else:
                brfi2 = brfi2 + 1
        else:  # 数据深度从深到浅
            if s1.cdp[ii] - s1.cdp[ii + 1] > 15:   # 当前cdp与下一个cdp的差小于等于15
                brfi2 = brfi2 + 1
            else:
                brfi1 = brfi1 + 1

    seismic_width5 = brfi1 / (2 * tpi) + (brfi2 + 2) / tpi  # 拉平在画布上的宽度
    seismic_height_raw = ips * (cfg['trange'][1] - cfg['trange'][0])  # 拉平在画布上的高度
    w1 = seismic_width5
    # print('拉平在画布上的的宽度', w1, brfi1, brfi2, tpi)  # 9.84251968503937 104 196
    # print('高度', seismic_height_raw)  # 13.858267716535433

    imsize = np.shape(im)
    # print(imsize)  # (1984, 3431, 4)，高度，宽度，通道数rgba
    scal = (imsize[1] - 158) / (cfg['zhuzidepmax'] - cfg['zhuzidepmin'])

    if cfg['zhuzidepmax'] < cfg['lped'] + 20 + cfg['kb']:
        w6 = ((cfg['zhuzidepmax']
               - (cfg['lpsd'] + cfg['kb'] - 20)) * scal + 158) / scal / (
            cfg['lped'] - cfg['lpsd'] + 40) * seismic_width5
    else:
        w6 = ((cfg['lped'] + 40 - cfg['lpsd']) * scal + 158) / scal / (
            cfg['lped'] - cfg['lpsd'] + 40) * seismic_width5

    # print('w6:', w6)  # 10.336660483892308

    w8 = imsize[0] / scal / (cfg['lped'] - cfg['lpsd'] + 40) * seismic_width5  # 岩性柱子的高度
    w7 = 136 / scal / (cfg['lped'] - cfg['lpsd'] + 40) * seismic_width5

    h_reqd = mb + seismic_height_raw + mt + w8  # inches

    w2 = (s2.ntraces + 1) / tpi
    w3 = (s2.ntraces + 1) / tpi  # 出来是20道，只需要10道

    stkcdp = 0
    maxjuli = 9999999
    for i in range(s4.ntraces):
        juli = math.sqrt((s2.wellx[0]*1.0 - s4.cdpx[i])
                         ** 2 + (s2.welly[0]*1.0 - s4.cdpy[i]) ** 2)
        if juli < maxjuli:
            maxjuli = juli
            stkcdp = i

    print(stkcdp, maxjuli)  # 563 15.297058540778355
    w4 = (cfg['sein'] + 1) / tpi  # 地面数据的宽度
    h = h_reqd
    seismic_width = w1 + w2 + w3 + w4 + mr + ml  # 画布的宽度
    seismic_left = ml / seismic_width
    seismic_bottom = (mb / h)
    # seismic_top = (mt / h)

    seismic_width_fraction1 = w1 / seismic_width  # 拉平宽度
    seismic_width_fraction2 = w2 / seismic_width  # 走廊
    seismic_width_fraction3 = w3 / seismic_width  # 滤波走廊
    seismic_width_fraction4 = w4 / seismic_width  # 地面数据
    seismic_width_fraction6 = w6 / seismic_width  # 岩性柱子
    seismic_width_fraction7 = (w6 - w7 - w1) / seismic_width

    seismic_height_fraction = seismic_height_raw / h
    seismic_height_fraction2 = w8 / h

    w = seismic_width

    # Set the tickformat.
    tickfmt = mtick.FormatStrFormatter('%.0f')

    cfg['fontsize'] = cfg['fontsize'] or 30

    # config = {
    #     "font.family": 'serif',
    #     "font.size": 20,
    #     "mathtext.fontset": 'stix',
    #     "font.sans-serif": 'SimSun',
    # }

    plt.rcParams['font.sans-serif'] = ['SimHei']  # 显示中文标签

    plt.rcParams['mathtext.default'] = 'regular'

    plt.rcParams['axes.unicode_minus'] = False
    fig = plt.figure(figsize=(w, h), facecolor='w', dpi=300)

    # left，bottom，width，height
    rect_line1 = [seismic_left, seismic_bottom, seismic_width_fraction1,
                  seismic_height_fraction]
    rect_line2 = [seismic_left + seismic_width_fraction1, seismic_bottom,
                  seismic_width_fraction2, seismic_height_fraction]
    rect_line3 = [seismic_left + seismic_width_fraction1
                  + seismic_width_fraction2,
                  seismic_bottom, seismic_width_fraction3,
                  seismic_height_fraction]
    rect_line4 = [seismic_left + seismic_width_fraction1
                  + seismic_width_fraction2 + seismic_width_fraction3,
                  seismic_bottom, seismic_width_fraction4,
                  seismic_height_fraction]
    rect_line5 = [seismic_left + seismic_width_fraction1
                  + seismic_width_fraction2 + seismic_width_fraction3,
                  seismic_bottom + seismic_height_fraction,
                  seismic_width_fraction4,
                  1.0 - seismic_bottom - seismic_height_fraction
                  - seismic_height_fraction2]
    rect_line6 = [seismic_left - seismic_width_fraction7, seismic_bottom
                  + seismic_height_fraction,
                  seismic_width_fraction6, seismic_height_fraction2]

    # ax_inline.set_xticklabels(ticklable)
    # fig.add_axes(ax_cof)
    zhuzi = fig.add_axes(rect_line6)
    ax5 = fig.add_axes(rect_line5)
    ax1 = fig.add_axes(rect_line1)
    ax2 = fig.add_axes(rect_line2)
    ax3 = fig.add_axes(rect_line3)
    ax4 = fig.add_axes(rect_line4)

    # ax5 = fig.add_axes(rect_line5)

    ax2.set_yticks([])
    ax3.set_yticks([])
    ax2.set_xticks([])
    ax3.set_xticks([])
    ax4.yaxis.set_ticks_position('right')
    ax4.xaxis.set_ticks_position('top')
    ax5.xaxis.set_ticks_position('top')

    ax5.spines['right'].set_visible(False)
    ax5.spines['left'].set_visible(False)
    ax5.spines['top'].set_visible(False)
    ax5.tick_params(which="major", length=0)

    ax5.set_yticks([])

    # startindex=cfg['lpsd']+ cfg['kb']-20)-cfg['zhuzidepmin']

    startindex = (cfg['lpsd'] + cfg['kb'] - 20 -
                  cfg['zhuzidepmin']) * scal + 136
    endindex = (cfg['lped'] + cfg['kb'] + 20 - cfg['zhuzidepmin']) * scal + 136
    del_index = []
    for col in range(imsize[1]):
        if col < startindex and col > 136:
            del_index.append(col)
        if col > endindex and col < (imsize[1] - 21):
            del_index.append(col)

    im = np.delete(im, del_index, axis=1)

    zhuzi.imshow(im, aspect='auto')
    imsize1 = np.shape(im)
    zhuzi.set_xlim(0, imsize1[1])
    zhuzi.set_ylim(0, imsize1[0])
    if cfg['fcx'] == 1:
        for ii in range(0, len(dep)):
            if (dep[ii] > cfg['lped'] + cfg['kb']) or (
                    dep[ii] < cfg['lpsd'] + cfg['kb']):
                continue
            # xx = dep[ii] * ((imsize[1] - 158) / (
            # max(s1.cdp) + 63 + cfg['kb'])) + 136
            xx = (dep[ii] - cfg['lpsd'] - cfg['kb'] + 20) * scal + 136
            zhuzi.plot([xx, xx],
                       [0, imsize1[0]], 'r', lw=2.5 * cfg['lineweight'])
    # zhuzi.plot([135,135],
    #            [0, imsize[0]], 'r', lw=2.5 * cfg['lineweight'])
    # zhuzi.plot([3313,3513],
    #            [0, imsize[0]], 'r', lw=2.5 * cfg['lineweight'])

    print('sacl', scal)  # 0.629423076923077
    zhuzi.invert_xaxis()
    zhuzi.invert_yaxis()

    # ax4.yaxis.set_ticks_position('right')
    progress_wrapper.setValue(40)
    print(time.time() - start, '计算')

    [fbmin, fbmax, ax1, fctime] = s1.wiggle_plot(
        ax=ax1,
        skip=cfg['skip'],
        skip2=cfg['skip2'],
        gain=cfg['lpgain'],
        rgb=cfg['colour'],
        alpha=cfg['opacity'],
        lw=cfg['lineweight'],
        ts=cfg['trange'][0],
        td=cfg['trange'][1],
        kb=cfg['kb'],
        dir=cfg['direction'],
        stkw=cfg['stkw'],
        stkdep=cfg['stkdep'],
        fcx=cfg['fcx'],
        dep=dep,
        zu=zu,
        font=font,
        font1=font1,
        fzt=fzt,
        py=py,
        ywdh=ywdh,
        ywdhpy=ywdhpy,
        lped=cfg['lped'],
        lpsd=cfg['lpsd'],
    )
    print('************************')
    print("拉平 Plot OK!")

    ax2 = s2.wiggle_plot1(
        ax=ax2,
        skip=cfg['skip'],
        skip2=cfg['skip2'],
        gain=cfg['stkgain'],
        rgb=cfg['colour'],
        alpha=cfg['opacity'],
        lw=cfg['lineweight'],
        ts=cfg['trange'][0],
        td=cfg['trange'][1],
        fcx=cfg['fcx'],
        fctime=fctime,
        fbmin=fbmin,
        fbmax=fbmax,
    )
    print('************************')
    print("走廊 Plot OK!")

    ax3 = s3.wiggle_plot1(
        ax=ax3,
        skip=cfg['skip'],
        skip2=cfg['skip2'],
        gain=cfg['stkbfgain'],
        rgb=cfg['colour'],
        alpha=cfg['opacity'],
        lw=cfg['lineweight'],
        ts=cfg['trange'][0],
        td=cfg['trange'][1],
        times=cfg['times'],
        fcx=cfg['fcx'],
        fctime=fctime,
        fbmin=fbmin,
        fbmax=fbmax,
    )
    print('************************')
    print("滤波走廊 Plot OK!")

    ax4 = s4.wiggle_plot2(
        ax=ax4,
        skip=cfg['skip'],
        skip2=cfg['skip2'],
        gain=cfg['seigain'],
        rgb=cfg['colour'],
        alpha=cfg['opacity'],
        lw=cfg['lineweight'],
        ts=cfg['trange'][0],
        td=cfg['trange'][1],
        times=cfg['seitimes'],
        stt=stkcdp,
        sein=cfg['sein'],
        fcx=cfg['fcx'],
        fctime=fctime,
        fbmin=fbmin,
        fbmax=fbmax,
    )
    progress_wrapper.setValue(75)
    print(time.time() - start, '绘制')
    print('************************')
    print("地面地震 Plot OK!")
    print("Start Save!")

    ax1.set_ylabel('Time(ms)',
                   fontsize=cfg['fontsize'] - 20)
    ax1.set_xlabel('Depth(m)',
                   fontsize=cfg['fontsize'] - 20,
                   ha='center')

    y_major_locator = MultipleLocator(cfg['timeskip'])
    ax1.yaxis.set_major_locator(y_major_locator)
    # ticks_loc = np.arange(cfg['trange'][0]*1000,
    # cfg['trange'][1] * 1000.0, cfg['timeskip'])
    # ax1.set_yticks(ticks_loc)
    # ax.set_yticks(ax.get_yticks().tolist())
    # ax1.set_yticklabels(ticks_loc, fontsize=cfg['fontsize'] - 20)

    ticks_loc = np.arange(int(ax1.viewLim.x1), int(
        ax1.viewLim.x0), cfg['skip3'])

    if (cfg['lped'] - ticks_loc[-1]) < 200:
        ticks_loc[-1] = cfg['lped']
    else:
        np.append(ticks_loc, cfg['lped'])
        # ticks_loc.append(max(s1.cdp))
        # ticks_loc = ax.get_xticks().tolist()
        # 先将p_变成list形式进行拼接，注意输入为一个tuple
        # ticks_loc = np.concatenate((ticks_loc, [max(s1.cdp)]))
        ticks_loc = np.append(ticks_loc, cfg['lped'])
    ax1.set_xticks(ticks_loc)
    ax1.set_xticklabels(ticks_loc, fontsize=cfg['fontsize'] - 20)

    ax1.xaxis.set_major_formatter(tickfmt)
    ax1.yaxis.set_major_formatter(tickfmt)
    ax1.set_ylim(1000 * cfg['trange'][1] or 1000 * s1.tbasis[-1],
                 1000 * cfg['trange'][0])

    ax1.xaxis.set_ticks_position('top')
    ax1.xaxis.set_label_position('top')
    ax1.tick_params(axis='x', width=cfg['lineweight'], colors='black')

    ax2.set_ylim(1000 * cfg['trange'][1] or 1000 * s1.tbasis[-1],
                 1000 * cfg['trange'][0])

    ax3.set_ylim(1000 * cfg['trange'][1] or 1000 * s1.tbasis[-1],
                 1000 * cfg['trange'][0])

    ax4.set_ylim(1000 * cfg['trange'][1]
                 + cfg['seitimes'] or 1000 * s1.tbasis[-1],
                 1000 * cfg['trange'][0] + cfg['seitimes'])
    y_major_locator1 = MultipleLocator(cfg['timeskip'])
    ax4.yaxis.set_major_locator(y_major_locator1)

    # ax_cof.axis['bottom'].set_visible(False)
    # ax_cof.axis['top'].set_visible(True)

    ticks_loc = np.arange(20, 20 * (cfg['sein'] - 10) + 20, 300)

    ticks_loc = np.append(ticks_loc, 20 * cfg['sein'] + 20)

    ax4.set_xticks(ticks_loc)
    ticklable = s4.inlin[stkcdp:stkcdp + cfg['sein'] - 10:15]
    ticklable = np.append(ticklable, 'InLine')

    ax4.set_xticklabels(ticklable, fontsize=cfg['fontsize'] - 20)

    ax5.set_xlim(0, 20 * cfg['sein'] + 20)
    ax5.set_xticks(ticks_loc)
    ticklable = s4.crosslin[stkcdp:stkcdp + cfg['sein'] - 10:15]
    ticklable = np.append(ticklable, 'CrossLine')
    ax5.set_xticklabels(ticklable, fontsize=cfg['fontsize'] - 20)
    zhuzi.axis('off')
    # ax5.axis('off')
    progress_wrapper.setValue(80)
    print(time.time() - start, '调整')

    # ax5.axis["新建1"] = ax5.new_fixed_axis(loc="top", offset=(0,-50))

    # ticks_loc = np.arange(1000*cfg['trange'][0]+cfg['times']
    # , cfg['trange'][1] * 1000.0+cfg['times'] , cfg['timeskip'])
    # ax4.set_yticks(ticks_loc)
    #     # ax.set_yticks(ax.get_yticks().tolist())
    # ax4.set_yticklabels(ticks_loc, fontsize=cfg['fontsize'] - 20)

    #####################################################################
    # SAVE FILE
    #####################################################################

    # outfile = cfg['outfile']
    # fig.savefig(outfile, bbox_inches='tight', transparent=True)
    # fig.savefig(outfile, bbox_inches='tight', )

    # arr = cfg['outfile'].split(".")
    # arr[len(arr) - 1] = "png"
    # outfile = ".".join(arr)
    outfile = resource_path("./static/img/provisional.png")
    fig.savefig(outfile, bbox_inches='tight')  # 支持eps, jpeg, jpg, pdf, pgf, png, ps, raw, rgba, svg, svgz, tif, tiff, webp
    imageRotationPre = Image.open(outfile)
    rotated_image = imageRotationPre.rotate(cfg['angle'], expand=True)

    rotated_image.save(cfg['outfile'])

    print(time.time() - start, '完成')
    progress_wrapper.setValue(100)
    print('************************')
    print("保存完成")
    print('************************')
    return


def bridgeDiagram(cfg, progress_wrapper):
    data_copy = copy.deepcopy(cfg)
    data_copy['tpi'] = data_copy['tpi'] * 2.54
    data_copy['ips'] = data_copy['ips'] / 2.54
    start = time.time()
    vspplot(data_copy, progress_wrapper)
    end = time.time()
    print(f'桥图运行时长：{end - start}秒')
    # saveRecord(record, 'success', 'static/json/bridgeDiagram.json')
    return {
        'status': 'success'
    }
    # try:
    #     cfg['tpi'] = cfg['tpi'] * 2.54
    #     cfg['ips'] = cfg['ips'] / 2.54
    #     start = time.time()
    #     vspplot(cfg)
    #     end = time.time()
    #     print(f'桥图运行时长：{end - start}秒')
    #     # saveRecord(record, 'success', 'static/json/bridgeDiagram.json')
    #     return {
    #         'status': 'success'
    #     }
    # except Exception as e:
    #     print('************************\n error:', e)
    #     # saveRecord(record, 'error', 'static/json/bridgeDiagram.json')
    #     return {
    #         'status': 'error',
    #         'msg': str(e),
    #         'detail': traceback.format_exc()
    #     }
